package com.hzit.loan.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hzit.loan.pay.commonApi.enums.PayChannelEnum;
import com.hzit.loan.pay.commonApi.enums.PayStatusEnum;
import com.hzit.loan.pay.commonApi.req.PayQueryReq;
import com.hzit.loan.pay.commonApi.req.PayReq;
import com.hzit.loan.pay.commonApi.resp.PayNotifyData;
import com.hzit.loan.pay.commonApi.resp.PayResultData;
import com.hzit.loan.pay.commonApi.resp.RespVo;
import com.hzit.loan.pay.commonApi.resp.TradeCloseRespData;
import com.hzit.loan.pay.commonApi.utils.PayDigestUtil;
import com.hzit.loan.pay.factory.PayStrategyFactory;
import com.hzit.loan.pay.iClient.IAlipayFrontClient;
import com.hzit.loan.pay.mapper.MchInfoMapper;
import com.hzit.loan.pay.mapper.MchPayWayMapper;
import com.hzit.loan.pay.model.MchInfo;
import com.hzit.loan.pay.model.MchPayWay;
import com.hzit.loan.pay.model.PaySerial;
import com.hzit.loan.pay.service.IPaySerialService;
import com.hzit.loan.pay.service.IPayService;
import com.hzit.loan.pay.service.IPayStrategyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.Date;
import java.util.Map;

/**
 * 支付接口具体实现
 */
@Service
public class PayServiceImpl implements IPayService {


    @Autowired
    private MchInfoMapper mchInfoMapper;

    @Autowired
    private MchPayWayMapper mchPayWayMapper;

    @Autowired
    private IPaySerialService paySerialService;

    @Autowired
    private IAlipayFrontClient alipayFrontClient;

    private Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);

    /**
     * 支付
     * @param payReq
     * @return
     */
    @Override
    public  RespVo<PayResultData> doPay(PayReq payReq) {

        /*************1.判断商户号是否存在，并且状态是否可用********************/

        String mchId = payReq.getMchId();
        //TODO 先查redis，redis没有在查db
        MchInfo mchInfo = mchInfoMapper.queryMchInfoByMchId(mchId);
        if (ObjectUtils.isEmpty(mchInfo)  ){
            logger.info("订单号：{}:商户号不存在或状态不可用",payReq.getMchOrderId());
            return RespVo.getFailReturn("商户号不存在或状态不可用");
        }
        /******************判断商户号是否存在，并且状态是否可用**********************/


        /*************2.验证请求参数是否被串改********************/
        //获取业务系统的签名
        String sign = payReq.getSign();
        //java对象转map
        Map map = JSONObject.parseObject(JSONObject.toJSONString(payReq), Map.class);
        String newSign = PayDigestUtil.getSign(map,mchInfo.getReqKey(),"sign");
        if(!sign.equals(newSign)){
            logger.info("订单号：{}:请求非法",payReq.getMchOrderId());
            return RespVo.getFailReturn("请求非法");
        }
        /*************2.验证请求参数是否被串改********************/


        /**************3.判断是否支持该支付方式，并且状态是否可用**************/
        MchPayWay mchPayWay = mchPayWayMapper.queryByMchIdAndPayChannel(payReq.getMchId(),payReq.getPayChannel(),
                payReq.getPayWay());

        if(ObjectUtils.isEmpty(mchPayWay)){
            logger.info("订单号：{}:商户支付方式不存在或状态不可用",payReq.getMchOrderId());
            return RespVo.getFailReturn("商户支付方式不存在或状态不可用");
        }
        /**************判断是否支持该支付方式，并且状态是否可用**************/



        /***********************生成支付流水***************************/
        PaySerial paySerial = paySerialService.addPaySerial(payReq);

        if(ObjectUtils.isEmpty(paySerial)){
            logger.info("订单号：{}:已经存在待支付订单",payReq.getMchOrderId());
            return RespVo.getFailReturn("已经存在待支付订单");
        }

//        if(payReq.getPayWay().equals("支付宝扫码支付")){
//
//            IPayStrategyService payStrategyService = new AliapySmPayImpl();
//        }else if(payReq.getPayWay().equals("微信扫码支付")){
//            IPayStrategyService payStrategyService = new WechatQrCodePayImpl();
//
//        }

        //策略模式+ 工厂模式
        IPayStrategyService payStrategyService = PayStrategyFactory.getPayStrategy(payReq.getPayWay());

        if (ObjectUtils.isEmpty(payStrategyService)){
            logger.info("订单号：{}:不支持该支付方式",payReq.getMchOrderId());
            return RespVo.getFailReturn("不支持该支付方式");
        }

        RespVo<PayResultData> respVo = payStrategyService.pay(paySerial);

        return respVo;
    }

    /**
     * 支付查询
     * @param payQueryReq
     * @return
     */
    @Override
    public RespVo<PayNotifyData> query(PayQueryReq payQueryReq) {


        //2.签名验证 TODO

        RespVo<PayNotifyData> respVo = new RespVo<PayNotifyData>();
        PayNotifyData payNotifyData = new PayNotifyData();

        //3.查询本地数据库的状态
        PaySerial paySerial =  paySerialService.queryByPaySerialNoOrMchOrderNo(payQueryReq.getPaySerialNo(),payQueryReq.getMcOrderNo());
        if(ObjectUtils.isEmpty(paySerial)){
            logger.info("订单号：{},流水号：{},没有找到对应的支付记录", payQueryReq.getMcOrderNo(),payQueryReq.getPaySerialNo());
            return RespVo.getFailReturn("没有找到对应的支付记录");
        }
//
        //4.数据库存在成功或者失败直接返回
        if(paySerial.getStatus().equals(PayStatusEnum.FAIL.getCode())
                || paySerial.getStatus().equals(PayStatusEnum.SUCCESS.getCode()) ){

            respVo.setCode(0);
            respVo.setMsg("请求成功");

//          BeanUtils.copyProperties(paySerial,payNotifyData); TODO
            payNotifyData.setPayWay(paySerial.getPayWay());
            payNotifyData.setPayChannel(paySerial.getPayChannel());
            payNotifyData.setMchOrderId(paySerial.getMchOrderNo());
            payNotifyData.setTradeStatus(paySerial.getStatus());
            payNotifyData.setFinishedTime(paySerial.getPaySuccessTime());

            //TODO 生成sign
            String sign = "";
            payNotifyData.setSign(sign);
            return respVo;
        }
//        //5.本地库订单还是未支付，调用银行或者支付公司接口。
        if (paySerial.getPayChannel().equals(PayChannelEnum.ALIPAY.getCode())){

            respVo =  alipayFrontClient.payQuery(paySerial.getPaySerialNo());

            if(0 == respVo.getCode()){

                //更新流水表中的状态
                payNotifyData = respVo.getData();
                PaySerial record = new PaySerial();
                record.setStatus(payNotifyData.getTradeStatus());
                record.setBankRespNo(payNotifyData.getStatusDesc());
//              record.setBankRespNo(payNotifyData.get);
                paySerialService.updatePaySerialNo(record);

//                payNotifyData.setPayWay();

                //封装返回

            }

            return respVo;

        } else if(paySerial.getPayChannel().equals(PayChannelEnum.WECHAT.getCode())){

        }

        //5.根据支付公司支付结果，更新支付流水，并返回给业务系统
        return null;
    }

    @Override
    public RespVo<?> close() {

        RespVo<TradeCloseRespData>  respVo =  alipayFrontClient.tradeClose(null);

        if(0 == respVo.getCode()){
            paySerialService.updatePaySerial(null);

        }

        //封装返回

        return null;
    }
}
